#pragma once

namespace ManagedVC1
{
    template <typename T>
    ref struct AutoArrayPtr
    {
        AutoArrayPtr() : m_ptr(nullptr) {}
        AutoArrayPtr(T* ptr) : m_ptr(ptr) {}
        AutoArrayPtr(AutoArrayPtr<T>% right) : m_ptr(right.Release()) {}

        ~AutoArrayPtr()
        {
            if (m_ptr != nullptr) delete[] m_ptr;
            m_ptr = nullptr;
        }
        !AutoArrayPtr()
        {
            ASSERT(nullptr == m_ptr);
            delete[] m_ptr;
        }
        T* operator->()
        {
            if (nullptr == m_ptr)
            {
                throw gcnew ObjectDisposedException(String::Empty);
            }

            return m_ptr;
        }
        operator T*()
        {
            if (nullptr == m_ptr)
            {
                throw gcnew ObjectDisposedException(String::Empty);
            }

            return m_ptr;
        }

        T* GetPointer()
        {
            return m_ptr;
        }
        T& GetRef()
        {
            if (nullptr == m_ptr)
            {
                throw gcnew ObjectDisposedException(String::Empty);
            }

            return *m_ptr;
        }
        T* Release()
        {
            T* released = m_ptr;
            m_ptr = nullptr;
            return released;
        }
        void Reset()
        {
            Reset(nullptr);
        }
        void Reset(T* ptr)
        {
            if (ptr != m_ptr)
            {
                if (m_ptr != nullptr) delete[] m_ptr;
                m_ptr = ptr;
            }
        }

    private:
        T* m_ptr;
    };
}
